<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>简单网络架构图</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }

        .container {
            width: 100%;
            max-width: 900px;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 12px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
            overflow: hidden;
            padding: 25px;
        }

        header {
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 20px;
            border-bottom: 1px solid #eaeaea;
        }

        h1 {
            color: #2c3e50;
            font-size: 2.2rem;
            margin-bottom: 10px;
        }

        .description {
            color: #7f8c8d;
            font-size: 1rem;
            max-width: 700px;
            margin: 0 auto;
            line-height: 1.6;
        }

        .network-container {
            position: relative;
            width: 100%;
            height: 500px;
            background: #f9f9f9;
            border: 1px solid #ddd;
            border-radius: 8px;
            overflow: hidden;
            margin-bottom: 20px;
        }

        #network-svg {
            width: 100%;
            height: 100%;
        }

        .node {
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .node:hover {
            filter: brightness(1.2);
            transform: scale(1.05);
        }

        .node-label {
            font-size: 12px;
            font-weight: bold;
            text-anchor: middle;
            pointer-events: none;
            fill: white;
        }

        .link {
            stroke: #95a5a6;
            stroke-width: 2;
            fill: none;
            transition: all 0.3s ease;
        }

        .link:hover {
            stroke: #3498db;
            stroke-width: 3;
        }

        .link-label {
            font-size: 10px;
            font-weight: bold;
            fill: #e74c3c;
            text-anchor: middle;
            pointer-events: none;
        }

        .tooltip {
            position: absolute;
            padding: 10px;
            background: rgba(0, 0, 0, 0.85);
            color: white;
            border-radius: 6px;
            pointer-events: none;
            font-size: 14px;
            z-index: 10;
            max-width: 250px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .tooltip h3 {
            margin-bottom: 5px;
            color: #3498db;
        }

        .tooltip p {
            margin-bottom: 3px;
            line-height: 1.4;
        }

        .controls {
            display: flex;
            justify-content: center;
            gap: 15px;
            margin-bottom: 20px;
        }

        button {
            background: #3498db;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.3s ease;
            font-weight: 600;
        }

        button:hover {
            background: #2980b9;
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }

        footer {
            text-align: center;
            margin-top: 20px;
            color: #7f8c8d;
            font-size: 0.9rem;
        }

        @keyframes pulse {
            0% { opacity: 0.7; }
            50% { opacity: 1; }
            100% { opacity: 0.7; }
        }

        .pulse {
            animation: pulse 2s infinite;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>简单网络架构图</h1>
            <p class="description">包含四个设备的简单网络架构：防火墙、核心交换机、接入交换机和服务器</p>
        </header>

        <div class="controls">
            <button id="updateTrafficBtn">更新流量</button>
            <button id="resetViewBtn">重置视图</button>
        </div>

        <div class="network-container">
            <svg id="network-svg" viewBox="0 0 800 400"></svg>
            <div class="tooltip" id="tooltip"></div>
        </div>

        <footer>
            <p>使用 SVG + JavaScript 构建 | 简单网络架构图示例</p>
        </footer>
    </div>

    <script>
        // 设备数据
        const devices = [
            { id: "firewall", name: "防火墙", type: "firewall", x: 100, y: 200, cpu: 45, memory: 60, status: "正常" },
            { id: "core-switch", name: "核心交换机", type: "switch", x: 300, y: 200, cpu: 30, memory: 40, status: "正常" },
            { id: "access-switch", name: "接入交换机", type: "switch", x: 500, y: 200, cpu: 20, memory: 30, status: "正常" },
            { id: "server", name: "服务器", type: "server", x: 700, y: 200, cpu: 65, memory: 75, status: "正常" }
        ];

        // 连接数据
        const connections = [
            { id: "link1", source: "firewall", target: "core-switch", bandwidth: 10000, traffic: 4500 },
            { id: "link2", source: "core-switch", target: "access-switch", bandwidth: 1000, traffic: 750 },
            { id: "link3", source: "access-switch", target: "server", bandwidth: 100, traffic: 45 }
        ];

        // 设备颜色映射
        const deviceColors = {
            firewall: "#e74c3c",
            switch: "#3498db",
            server: "#2ecc71"
        };

        // 初始化网络拓扑图
        function initNetwork() {
            const svg = document.getElementById('network-svg');
            const tooltip = document.getElementById('tooltip');

            // 清空SVG内容
            svg.innerHTML = '';

            // 创建箭头标记
            const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');

            const marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker');
            marker.setAttribute('id', 'arrowhead');
            marker.setAttribute('viewBox', '0 -5 10 10');
            marker.setAttribute('refX', 8);
            marker.setAttribute('refY', 0);
            marker.setAttribute('markerWidth', 6);
            marker.setAttribute('markerHeight', 6);
            marker.setAttribute('orient', 'auto');

            const markerPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            markerPath.setAttribute('d', 'M0,-5L10,0L0,5');
            markerPath.setAttribute('fill', '#95a5a6');

            marker.appendChild(markerPath);
            defs.appendChild(marker);
            svg.appendChild(defs);

            // 创建连接线
            connections.forEach(conn => {
                const sourceDevice = devices.find(d => d.id === conn.source);
                const targetDevice = devices.find(d => d.id === conn.target);

                if (!sourceDevice || !targetDevice) return;

                // 创建连接线
                const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                line.setAttribute('class', 'link');
                line.setAttribute('id', conn.id);
                line.setAttribute('x1', sourceDevice.x);
                line.setAttribute('y1', sourceDevice.y);
                line.setAttribute('x2', targetDevice.x);
                line.setAttribute('y2', targetDevice.y);
                line.setAttribute('marker-end', 'url(#arrowhead)');

                // 添加悬浮事件
                line.addEventListener('mouseover', function(e) {
                    const rect = svg.getBoundingClientRect();
                    const x = e.clientX - rect.left;
                    const y = e.clientY - rect.top;

                    tooltip.innerHTML = `
                        <h3>连接信息</h3>
                        <p><strong>源设备:</strong> ${sourceDevice.name}</p>
                        <p><strong>目标设备:</strong> ${targetDevice.name}</p>
                        <p><strong>带宽:</strong> ${conn.bandwidth} Mbps</p>
                        <p><strong>当前流量:</strong> ${conn.traffic} Mbps</p>
                        <p><strong>利用率:</strong> ${((conn.traffic / conn.bandwidth) * 100).toFixed(1)}%</p>
                    `;
                    tooltip.style.left = (x + 10) + 'px';
                    tooltip.style.top = (y - 10) + 'px';
                    tooltip.style.opacity = '1';

                    // 高亮连接线
                    line.style.stroke = '#3498db';
                    line.style.strokeWidth = '3';
                });

                line.addEventListener('mouseout', function() {
                    tooltip.style.opacity = '0';
                    line.style.stroke = '#95a5a6';
                    line.style.strokeWidth = '2';
                });

                svg.appendChild(line);

                // 创建流量标签
                const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
                text.setAttribute('class', 'link-label pulse');
                text.setAttribute('x', (sourceDevice.x + targetDevice.x) / 2);
                text.setAttribute('y', (sourceDevice.y + targetDevice.y) / 2);
                text.textContent = `${conn.traffic} Mbps`;

                svg.appendChild(text);
            });

            // 创建设备
            devices.forEach(device => {
                const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
                group.setAttribute('class', 'node');
                group.setAttribute('id', device.id);

                // 创建设备矩形
                const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                rect.setAttribute('width', '80');
                rect.setAttribute('height', '40');
                rect.setAttribute('x', device.x - 40);
                rect.setAttribute('y', device.y - 20);
                rect.setAttribute('rx', '5');
                rect.setAttribute('fill', deviceColors[device.type]);

                // 创建设备标签
                const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
                text.setAttribute('class', 'node-label');
                text.setAttribute('x', device.x);
                text.setAttribute('y', device.y + 5);
                text.textContent = device.name;

                group.appendChild(rect);
                group.appendChild(text);

                // 添加设备图标
                addDeviceIcon(group, device);

                // 添加悬浮事件
                group.addEventListener('mouseover', function(e) {
                    const rect = svg.getBoundingClientRect();
                    const x = e.clientX - rect.left;
                    const y = e.clientY - rect.top;

                    tooltip.innerHTML = `
                        <h3>${device.name}</h3>
                        <p><strong>类型:</strong> ${getDeviceTypeName(device.type)}</p>
                        <p><strong>CPU使用率:</strong> ${device.cpu}%</p>
                        <p><strong>内存使用率:</strong> ${device.memory}%</p>
                        <p><strong>状态:</strong> <span style="color: #2ecc71">${device.status}</span></p>
                    `;
                    tooltip.style.left = (x + 10) + 'px';
                    tooltip.style.top = (y - 10) + 'px';
                    tooltip.style.opacity = '1';

                    // 高亮设备
                    group.style.filter = 'brightness(1.2)';
                    group.style.transform = 'scale(1.05)';
                });

                group.addEventListener('mouseout', function() {
                    tooltip.style.opacity = '0';
                    group.style.filter = 'brightness(1)';
                    group.style.transform = 'scale(1)';
                });

                // 添加拖拽功能
                let isDragging = false;

                group.addEventListener('mousedown', function(e) {
                    isDragging = true;
                    group.style.cursor = 'grabbing';
                });

                document.addEventListener('mousemove', function(e) {
                    if (!isDragging) return;

                    const rect = svg.getBoundingClientRect();
                    const x = e.clientX - rect.left;
                    const y = e.clientY - rect.top;

                    // 更新设备位置
                    device.x = x;
                    device.y = y;

                    // 更新设备元素位置
                    rect.setAttribute('x', x - 40);
                    rect.setAttribute('y', y - 20);
                    text.setAttribute('x', x);
                    text.setAttribute('y', y + 5);

                    // 更新设备图标位置
                    updateDeviceIcon(group, device);

                    // 更新连接线位置
                    updateConnections(device);
                });

                document.addEventListener('mouseup', function() {
                    isDragging = false;
                    group.style.cursor = 'pointer';
                });

                svg.appendChild(group);
            });
        }

        // 添加设备图标
        function addDeviceIcon(group, device) {
            const iconGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');

            switch(device.type) {
                case 'firewall':
                    // 防火墙图标 - 矩形加对角线
                    const firewallRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                    firewallRect.setAttribute('x', device.x - 15);
                    firewallRect.setAttribute('y', device.y - 10);
                    firewallRect.setAttribute('width', '30');
                    firewallRect.setAttribute('height', '20');
                    firewallRect.setAttribute('fill', 'white');
                    firewallRect.setAttribute('rx', '3');
                    iconGroup.appendChild(firewallRect);

                    const diagonal1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    diagonal1.setAttribute('x1', device.x - 12);
                    diagonal1.setAttribute('y1', device.y - 7);
                    diagonal1.setAttribute('x2', device.x + 12);
                    diagonal1.setAttribute('y2', device.y + 7);
                    diagonal1.setAttribute('stroke', '#e74c3c');
                    diagonal1.setAttribute('stroke-width', '2');
                    iconGroup.appendChild(diagonal1);

                    const diagonal2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    diagonal2.setAttribute('x1', device.x - 12);
                    diagonal2.setAttribute('y1', device.y + 7);
                    diagonal2.setAttribute('x2', device.x + 12);
                    diagonal2.setAttribute('y2', device.y - 7);
                    diagonal2.setAttribute('stroke', '#e74c3c');
                    diagonal2.setAttribute('stroke-width', '2');
                    iconGroup.appendChild(diagonal2);
                    break;

                case 'switch':
                    // 交换机图标 - 矩形加端口线
                    const switchRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                    switchRect.setAttribute('x', device.x - 15);
                    switchRect.setAttribute('y', device.y - 8);
                    switchRect.setAttribute('width', '30');
                    switchRect.setAttribute('height', '16');
                    switchRect.setAttribute('fill', 'white');
                    switchRect.setAttribute('rx', '2');
                    iconGroup.appendChild(switchRect);

                    for (let i = 0; i < 3; i++) {
                        const portLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                        portLine.setAttribute('x1', device.x - 10 + i * 10);
                        portLine.setAttribute('y1', device.y - 8);
                        portLine.setAttribute('x2', device.x - 10 + i * 10);
                        portLine.setAttribute('y2', device.y + 8);
                        portLine.setAttribute('stroke', '#3498db');
                        portLine.setAttribute('stroke-width', '1.5');
                        iconGroup.appendChild(portLine);
                    }
                    break;

                case 'server':
                    // 服务器图标 - 矩形加水平线
                    const serverRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                    serverRect.setAttribute('x', device.x - 15);
                    serverRect.setAttribute('y', device.y - 8);
                    serverRect.setAttribute('width', '30');
                    serverRect.setAttribute('height', '16');
                    serverRect.setAttribute('fill', 'white');
                    serverRect.setAttribute('rx', '2');
                    iconGroup.appendChild(serverRect);

                    for (let i = 0; i < 3; i++) {
                        const serverLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                        serverLine.setAttribute('x1', device.x - 12);
                        serverLine.setAttribute('y1', device.y - 5 + i * 5);
                        serverLine.setAttribute('x2', device.x + 12);
                        serverLine.setAttribute('y2', device.y - 5 + i * 5);
                        serverLine.setAttribute('stroke', '#2ecc71');
                        serverLine.setAttribute('stroke-width', '1');
                        iconGroup.appendChild(serverLine);
                    }
                    break;
            }

            group.appendChild(iconGroup);
        }

        // 更新设备图标位置
        function updateDeviceIcon(group, device) {
            const iconGroup = group.querySelector('g:last-child');
            if (!iconGroup) return;

            // 清除现有图标
            iconGroup.innerHTML = '';

            // 重新添加图标
            switch(device.type) {
                case 'firewall':
                    const firewallRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                    firewallRect.setAttribute('x', device.x - 15);
                    firewallRect.setAttribute('y', device.y - 10);
                    firewallRect.setAttribute('width', '30');
                    firewallRect.setAttribute('height', '20');
                    firewallRect.setAttribute('fill', 'white');
                    firewallRect.setAttribute('rx', '3');
                    iconGroup.appendChild(firewallRect);

                    const diagonal1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    diagonal1.setAttribute('x1', device.x - 12);
                    diagonal1.setAttribute('y1', device.y - 7);
                    diagonal1.setAttribute('x2', device.x + 12);
                    diagonal1.setAttribute('y2', device.y + 7);
                    diagonal1.setAttribute('stroke', '#e74c3c');
                    diagonal1.setAttribute('stroke-width', '2');
                    iconGroup.appendChild(diagonal1);

                    const diagonal2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    diagonal2.setAttribute('x1', device.x - 12);
                    diagonal2.setAttribute('y1', device.y + 7);
                    diagonal2.setAttribute('x2', device.x + 12);
                    diagonal2.setAttribute('y2', device.y - 7);
                    diagonal2.setAttribute('stroke', '#e74c3c');
                    diagonal2.setAttribute('stroke-width', '2');
                    iconGroup.appendChild(diagonal2);
                    break;

                case 'switch':
                    const switchRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                    switchRect.setAttribute('x', device.x - 15);
                    switchRect.setAttribute('y', device.y - 8);
                    switchRect.setAttribute('width', '30');
                    switchRect.setAttribute('height', '16');
                    switchRect.setAttribute('fill', 'white');
                    switchRect.setAttribute('rx', '2');
                    iconGroup.appendChild(switchRect);

                    for (let i = 0; i < 3; i++) {
                        const portLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                        portLine.setAttribute('x1', device.x - 10 + i * 10);
                        portLine.setAttribute('y1', device.y - 8);
                        portLine.setAttribute('x2', device.x - 10 + i * 10);
                        portLine.setAttribute('y2', device.y + 8);
                        portLine.setAttribute('stroke', '#3498db');
                        portLine.setAttribute('stroke-width', '1.5');
                        iconGroup.appendChild(portLine);
                    }
                    break;

                case 'server':
                    const serverRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
                    serverRect.setAttribute('x', device.x - 15);
                    serverRect.setAttribute('y', device.y - 8);
                    serverRect.setAttribute('width', '30');
                    serverRect.setAttribute('height', '16');
                    serverRect.setAttribute('fill', 'white');
                    serverRect.setAttribute('rx', '2');
                    iconGroup.appendChild(serverRect);

                    for (let i = 0; i < 3; i++) {
                        const serverLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                        serverLine.setAttribute('x1', device.x - 12);
                        serverLine.setAttribute('y1', device.y - 5 + i * 5);
                        serverLine.setAttribute('x2', device.x + 12);
                        serverLine.setAttribute('y2', device.y - 5 + i * 5);
                        serverLine.setAttribute('stroke', '#2ecc71');
                        serverLine.setAttribute('stroke-width', '1');
                        iconGroup.appendChild(serverLine);
                    }
                    break;
            }
        }

        // 更新连接线位置
        function updateConnections(device) {
            const svg = document.getElementById('network-svg');

            // 找到所有连接到该设备的连接线
            connections.forEach(conn => {
                if (conn.source === device.id || conn.target === device.id) {
                    const sourceDevice = devices.find(d => d.id === conn.source);
                    const targetDevice = devices.find(d => d.id === conn.target);

                    if (!sourceDevice || !targetDevice) return;

                    // 更新连接线
                    const line = document.getElementById(conn.id);
                    if (line) {
                        line.setAttribute('x1', sourceDevice.x);
                        line.setAttribute('y1', sourceDevice.y);
                        line.setAttribute('x2', targetDevice.x);
                        line.setAttribute('y2', targetDevice.y);
                    }

                    // 更新流量标签位置
                    const linkLabels = svg.querySelectorAll('.link-label');
                    linkLabels.forEach(label => {
                        if (label.textContent === `${conn.traffic} Mbps`) {
                            label.setAttribute('x', (sourceDevice.x + targetDevice.x) / 2);
                            label.setAttribute('y', (sourceDevice.y + targetDevice.y) / 2);
                        }
                    });
                }
            });
        }

        // 获取设备类型名称
        function getDeviceTypeName(type) {
            const typeNames = {
                firewall: "防火墙",
                switch: "交换机",
                server: "服务器"
            };
            return typeNames[type] || type;
        }

        // 更新流量数据
        function updateTraffic() {
            const svg = document.getElementById('network-svg');

            connections.forEach(conn => {
                // 随机变化流量，但不超过带宽
                const change = (Math.random() - 0.5) * 50;
                conn.traffic = Math.max(10, Math.min(conn.bandwidth * 0.9, conn.traffic + change));
            });

            // 更新流量标签
            const linkLabels = svg.querySelectorAll('.link-label');
            linkLabels.forEach((label, index) => {
                if (index < connections.length) {
                    label.textContent = `${Math.floor(connections[index].traffic)} Mbps`;
                }
            });
        }

        // 初始化网络拓扑图
        document.addEventListener('DOMContentLoaded', function() {
            initNetwork();

            // 更新流量按钮
            document.getElementById('updateTrafficBtn').addEventListener('click', function() {
                updateTraffic();
            });

            // 重置视图按钮
            document.getElementById('resetViewBtn').addEventListener('click', function() {
                // 重置设备位置
                devices.forEach((device, index) => {
                    if (index === 0) device.x = 100, device.y = 200;
                    else if (index === 1) device.x = 300, device.y = 200;
                    else if (index === 2) device.x = 500, device.y = 200;
                    else if (index === 3) device.x = 700, device.y = 200;
                });

                initNetwork();
            });

            // 模拟实时流量更新
            setInterval(() => {
                updateTraffic();
            }, 3000);
        });
    </script>
</body>
</html>